﻿using SnClient;
using System;
using System.Diagnostics;
using System.Runtime.InteropServices;
using System.Text;

namespace CdmConsoleHelper
{
    public class ConsoleLogging : ILogging
    {
        public void LogOneEvent( LoggingEventId id, EventLogEntryType type, string info )
        {
            this.LogOneEvent( ( long )id, type, info );
        }

        public void LogOneEvent( LoggingEventId id, string info )
        {
            this.LogOneEvent( ( long )id, EventLogEntryType.Information, info );
        }

        public void LogOneEvent( long id, EventLogEntryType type, string info )
        {
            Console.WriteLine( "{0} ({1}): {2}", this.GetEventLogEntryTypeAsString( type ), id, info );
        }

        public void LogException( Exception e, string info )
        {
            String msg = BuildExceptionString( e, info );

            this.LogOneEvent( LoggingEventId.EVENT_ID_EXCEPTION, EventLogEntryType.Error, msg );
        }

        static private String BuildExceptionStringInternal( Exception e )
        {
            StringBuilder ret = new StringBuilder();
            ret.Append( BuildSingleExceptionString( e ) );
            if ( e.InnerException != null )
                ret.Append( BuildSingleExceptionString( e.InnerException ) );

            return ret.ToString();
        }

        static private String BuildSingleExceptionString( Exception e )
        {
            if ( e is SEHException )
            {
                SEHException seh = ( SEHException )e;
                return String.Format( "\nException: {0} {2}\n\n{1}\n", e.Message, e.StackTrace, seh.HResult );
            }

            return String.Format( "\nException: {0}\n\n{1}\n", e.Message, e.StackTrace );
        }

        static private String BuildExceptionString( Exception e, String info )
        {
            StringBuilder sb = new StringBuilder( info );
            if ( e is AggregateException )
            {
                AggregateException ae = ( AggregateException )e;
                foreach ( Exception inner in ae.InnerExceptions )
                    sb.Append( BuildExceptionStringInternal( inner ) );
            }
            else
            {
                sb.Append( BuildExceptionStringInternal( e ) );
            }

            return sb.ToString();
        }

        public void LogException( Exception e, long id, string info )
        {
            String msg = BuildExceptionString( e, info );

            this.LogOneEvent( id, EventLogEntryType.Error, msg );
        }

        public void LogException( Exception e, LoggingEventId id, string info )
        {
            this.LogException( e, ( long )id, info );
        }

        private string GetEventLogEntryTypeAsString( EventLogEntryType type )
        {
            switch ( type )
            {
                case EventLogEntryType.Error:
                    return "Error";

                case EventLogEntryType.FailureAudit:
                    return "Failure";

                case EventLogEntryType.Information:
                    return "Info";

                case EventLogEntryType.SuccessAudit:
                    return "Success";

                case EventLogEntryType.Warning:
                    return "Warning";

                default:
                    return "";
            }
        }
    }
}
